/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 */

package com.device.idea.demo.view.widget;

import static com.device.idea.demo.constant.Constant.CANVAS_SCALE_MAX_VALUE;
import static com.device.idea.demo.constant.Constant.CANVAS_SCALE_MIN_VALUE;
import static com.device.idea.demo.constant.Constant.PICKER_COLORS;
import static com.device.idea.demo.constant.Constant.PICKER_COLORS_DRAWABLE;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.GradientDrawable;
import android.util.Size;
import android.view.View;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.device.idea.demo.R;
import com.device.idea.demo.constant.Constant;
import com.device.idea.demo.core.RecognitionLang;
import com.device.idea.demo.core.RecognitionLangAdapter;
import com.device.idea.demo.databinding.PopWindowMoreBinding;
import com.device.idea.demo.util.LogUtil;
import com.device.idea.demo.view.WhiteBoardActivity;
import com.device.idea.whiteboard.WhiteboardServiceController;
import com.device.idea.whiteboard.callback.Callback;
import com.device.idea.whiteboard.model.LogLevel;
import com.device.idea.whiteboard.model.WhiteBoardEraser;
import com.device.idea.whiteboard.model.WhiteBoardImageType;
import com.device.idea.whiteboard.model.WhiteBoardPen;
import com.device.idea.whiteboard.model.WhiteBoardScaleType;
import com.device.idea.whiteboard.model.WhiteBoardSelector;
import com.device.idea.whiteboard.model.WhiteBoardTouchStyle;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 2.0 新增接口列表
 *
 * @since 2021-11-22
 */
public class MorePopWindow extends BaseToolbarPopupWindow {
    private static final String TAG = MorePopWindow.class.getSimpleName();

    private static final String FORMAT_STRING = "0x%08X";

    private static final int RECOGNITION_GRID_SPAN_COUNT = 4;

    private static final int GRADIENT_DRAWABLE_WIDTH = 50;

    private static final int GRADIENT_DRAWABLE_HEIGHT = 20;

    private View.OnClickListener mClickListener;

    private PopWindowMoreBinding binding;

    private WhiteboardServiceController mController;

    private WhiteBoardActivity whiteBoardActivity;

    private List<String> recognitionLangList;

    private List<String> curRecognitionLangList;

    private List<RecognitionLang> recognitionLangCtv;

    private RecyclerView mRecyclerView;

    private RecognitionLangAdapter mAdapter;

    private boolean isLogEnable;

    private LogLevel mLogLevel = LogLevel.INFO;

    /**
     * 构造函数
     *
     * @param context 上下文对象
     * @param width popupWindow的宽
     * @param height popupWindow的高
     * @param listener 点击回调监听
     */
    public MorePopWindow(@NonNull Context context, int width, int height, View.OnClickListener listener,
        WhiteBoardActivity whiteBoardActivity) {
        super(context, width, height, true);
        mClickListener = listener;
        this.whiteBoardActivity = whiteBoardActivity;
        mController = whiteBoardActivity.getController();
        binding.ivWhiteboardInfoExit.setOnClickListener(v -> {
            LogUtil.info(TAG, "WhiteboardInfoExit");
            mPopupWindow.dismiss();
        });
        binding.deleteSelection.setOnClickListener(v -> {
            LogUtil.info(TAG, "deleteSelection");
            mController.deleteSelection();
        });
        binding.unselectAnnotations.setOnClickListener(v -> {
            LogUtil.info(TAG, "unselectAnnotations");
            mController.unselectAnnots();
        });

        initCanvasListener();

        initSaveImageListener();

        binding.setPageBackgroundBitmap.setOnClickListener(v -> {
            LogUtil.info(TAG, "setPageBackgroundBitmap");
            Bitmap bitmap = Bitmap.createBitmap(Constant.DEFAULT_SCREEN_WIDTH, Constant.DEFAULT_SCREEN_HEIGHT,
                Bitmap.Config.ARGB_8888);
            bitmap.eraseColor(Constant.CANVAS_BACKGROUND_COLOR_BLACK_ARGB);
            mController.setPageBackground(bitmap, WhiteBoardScaleType.FIT_XY);
        });
        if (mClickListener != null) {
            binding.rearrangeToPre.setOnClickListener(mClickListener);
            binding.rearrangeToNext.setOnClickListener(mClickListener);
        }

        initRecognitionLang();

        initLogListener();

        // 给子控件间增加divider
        GradientDrawable drawable = new GradientDrawable();
        drawable.setSize(GRADIENT_DRAWABLE_WIDTH, GRADIENT_DRAWABLE_HEIGHT);
        binding.llTop.setDividerDrawable(drawable);
        binding.llTop.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
    }

    private void initLogListener() {
        binding.swLogSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                LogUtil.info(TAG, "swLogSwitch isChecked=" + isChecked);
                binding.swLogSwitch.setChecked(isChecked);
                isLogEnable = isChecked;
                binding.ctvLogDebug.setEnabled(isLogEnable);
                binding.ctvLogInfo.setEnabled(isLogEnable);
                binding.ctvLogWarn.setEnabled(isLogEnable);
                binding.ctvLogError.setEnabled(isLogEnable);
                mController.setLog(isLogEnable, mLogLevel);
            }
        });

        binding.ctvLogDebug.setOnClickListener(v -> {
            if (!binding.ctvLogDebug.isChecked()) {
                updateLogInfo(LogLevel.DEBUG);
            }
        });
        binding.ctvLogInfo.setOnClickListener(v -> {
            if (!binding.ctvLogInfo.isChecked()) {
                updateLogInfo(LogLevel.INFO);
            }
        });
        binding.ctvLogWarn.setOnClickListener(v -> {
            if (!binding.ctvLogWarn.isChecked()) {
                updateLogInfo(LogLevel.WARNING);
            }
        });
        binding.ctvLogError.setOnClickListener(v -> {
            if (!binding.ctvLogError.isChecked()) {
                updateLogInfo(LogLevel.ERROR);
            }
        });
    }

    private void updateLogInfo(LogLevel logLevel) {
        LogUtil.info(TAG, "logLevel=" + logLevel);
        mLogLevel = logLevel;
        if (logLevel == LogLevel.DEBUG) {
            binding.ctvLogDebug.setChecked(true);
            binding.ctvLogInfo.setChecked(false);
            binding.ctvLogWarn.setChecked(false);
            binding.ctvLogError.setChecked(false);
        } else if (logLevel == LogLevel.INFO) {
            binding.ctvLogDebug.setChecked(false);
            binding.ctvLogInfo.setChecked(true);
            binding.ctvLogWarn.setChecked(false);
            binding.ctvLogError.setChecked(false);
        } else if (logLevel == LogLevel.WARNING) {
            binding.ctvLogDebug.setChecked(false);
            binding.ctvLogInfo.setChecked(false);
            binding.ctvLogWarn.setChecked(true);
            binding.ctvLogError.setChecked(false);
        } else {
            binding.ctvLogDebug.setChecked(false);
            binding.ctvLogInfo.setChecked(false);
            binding.ctvLogWarn.setChecked(false);
            binding.ctvLogError.setChecked(true);
        }
        mController.setLog(isLogEnable, mLogLevel);
    }

    private void initCanvasListener() {
        binding.canvasScaleDec.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasScaleDec");

            // Canvas未锁定时才支持缩放
            if (!mController.isCanvasLock()) {
                int currentScale = mController.getCanvasScale();
                if (currentScale > CANVAS_SCALE_MIN_VALUE) {
                    currentScale -= 1;
                    mController.setCanvasScale(currentScale);
                    binding.tvCanvasScaleValue.setText(String.valueOf(currentScale));
                }
            }
        });
        binding.canvasScaleInc.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasScaleInc");

            // Canvas未锁定时才支持缩放
            if (!mController.isCanvasLock()) {
                int currentScale = mController.getCanvasScale();
                if (currentScale < CANVAS_SCALE_MAX_VALUE) {
                    currentScale += 1;
                    mController.setCanvasScale(currentScale);
                    binding.tvCanvasScaleValue.setText(String.valueOf(currentScale));
                }
            }
        });
        binding.canvasPositionUp.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasPositionUp");
            Point currentPos = mController.getCanvasPosition();
            currentPos.y += 1;
            updateCanvasPosition(currentPos);
        });
        binding.canvasPositionDown.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasPositionDown");
            Point currentPos = mController.getCanvasPosition();
            currentPos.y -= 1;
            updateCanvasPosition(currentPos);
        });
        binding.canvasPositionLeft.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasPositionLeft");
            Point currentPos = mController.getCanvasPosition();
            currentPos.x -= 1;
            updateCanvasPosition(currentPos);
        });
        binding.canvasPositionRight.setOnClickListener(v -> {
            LogUtil.info(TAG, "canvasPositionRight");
            Point currentPos = mController.getCanvasPosition();
            currentPos.x += 1;
            updateCanvasPosition(currentPos);
        });
    }

    private void initSaveImageListener() {
        binding.savePngImage.setOnClickListener(v -> {
            LogUtil.info(TAG, "savePngImage");
            String savePath = whiteBoardActivity.getFilesDir().getPath() + File.separator + "test.png";
            mController.savePageAsImage(whiteBoardActivity.getCurrentPageNum(), savePath,
                new Size(Constant.DEFAULT_SCREEN_WIDTH, Constant.DEFAULT_SCREEN_HEIGHT));
        });
        binding.saveJpgImage.setOnClickListener(v -> {
            LogUtil.info(TAG, "saveJpgImage");
            String savePath = whiteBoardActivity.getFilesDir().getPath() + File.separator + "test.jpeg";
            mController.savePageAsImage(whiteBoardActivity.getCurrentPageNum(), savePath,
                new Size(Constant.DEFAULT_SCREEN_WIDTH, Constant.DEFAULT_SCREEN_HEIGHT));
        });
        binding.savePngImageBuffer.setOnClickListener(v -> {
            LogUtil.info(TAG, "savePngImageBuffer");
            mController.savePageAsImage(whiteBoardActivity.getCurrentPageNum(),
                new Size(Constant.DEFAULT_SCREEN_WIDTH, Constant.DEFAULT_SCREEN_HEIGHT), WhiteBoardImageType.PNG,
                savePageAsImageCallback());
        });
        binding.saveJpgImageBuffer.setOnClickListener(v -> {
            LogUtil.info(TAG, "saveJpgImageBuffer");
            mController.savePageAsImage(whiteBoardActivity.getCurrentPageNum(),
                new Size(Constant.DEFAULT_SCREEN_WIDTH, Constant.DEFAULT_SCREEN_HEIGHT), WhiteBoardImageType.JPEG,
                savePageAsImageCallback());
        });
    }

    private void initRecognitionLang() {
        recognitionLangList = mController.getRecognitionLang();
        curRecognitionLangList = new ArrayList<>();
        recognitionLangCtv = new ArrayList<>();
        for (String lang : recognitionLangList) {
            curRecognitionLangList.add(lang);
            RecognitionLang langCtv = new RecognitionLang(lang, true);
            recognitionLangCtv.add(langCtv);
        }
        mRecyclerView = binding.recognitionLangRecyclerview;
        GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, RECOGNITION_GRID_SPAN_COUNT);
        gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(gridLayoutManager);
        mAdapter = new RecognitionLangAdapter(mContext, recognitionLangCtv, R.layout.recognition_lang);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener((view, itemData, position) -> {
            CheckedTextView checkedTextView = (CheckedTextView) view.findViewById(R.id.ctv_recognition_lang);
            checkedTextView.toggle();
            itemData.setChecked(!itemData.isChecked());
            if (itemData.isChecked()) {
                if (!curRecognitionLangList.contains(itemData.getLangName())) {
                    curRecognitionLangList.add(itemData.getLangName());
                }
            } else {
                if (curRecognitionLangList.contains(itemData.getLangName())) {
                    curRecognitionLangList.remove(itemData.getLangName());
                }
            }
        });
        binding.setRecognitionLang.setOnClickListener(v -> {
            LogUtil.info(TAG, "setRecognitionLang");
            mController.setRecognitionLang(curRecognitionLangList);
        });
    }

    @NonNull
    private Callback<byte[]> savePageAsImageCallback() {
        return new Callback<byte[]>() {
            @Override
            public void onSuccess(byte[] bytes) {
                LogUtil.info(TAG, "save image buffer success");
            }

            @Override
            public void onFailed(int errCode, String errMsg) {
                LogUtil.error(TAG, "save image buffer fail, errCode=" + errCode + ",errMsg=" + errMsg);
            }
        };
    }

    /**
     * 更新白板信息
     */
    public void updateWhiteboardInfo() {
        // 操作模式
        binding.tvTouchModeValue.setText(mController.getTouchMode().name());

        updatePen();

        // 橡皮擦样式
        WhiteBoardEraser[] erasers = mController.getEraserStyle();
        binding.tvEraseColorValue.setText(String.format(Locale.ROOT, FORMAT_STRING, erasers[0].getColor()));
        binding.tvEraseTypeValue.setText(erasers[0].getEraserType().name());
        binding.tvEraseShapeValue.setText(erasers[0].getShape().name());
        binding.tvEraseWidthValue.setText(String.valueOf(erasers[0].getWidth()));
        binding.tvEraseBorderColorValue.setText(String.format(Locale.ROOT, FORMAT_STRING, erasers[0].getBorderColor()));
        binding.tvEraseBorderWidthValue.setText(String.valueOf(erasers[0].getBorderWidth()));

        // 圈选线样式
        WhiteBoardSelector whiteBoardSelector = mController.getSelectorStyle();
        binding.tvSelectorLineColorValue
            .setText(String.format(Locale.ROOT, FORMAT_STRING, whiteBoardSelector.getLineColor()));
        binding.tvSelectorLineWidthValue.setText(String.valueOf(whiteBoardSelector.getLineWidth()));
        binding.tvSelectorOutlineColorValue
            .setText(String.format(Locale.ROOT, FORMAT_STRING, whiteBoardSelector.getOutlineColor()));
        binding.tvSelectorOutlineWidthValue.setText(String.valueOf(whiteBoardSelector.getOutlineWidth()));
        binding.tvSelectorBorderColorValue
            .setText(String.format(Locale.ROOT, FORMAT_STRING, whiteBoardSelector.getBorderColor()));
        binding.tvSelectorConnectCornerLineWidthValue
            .setText(String.valueOf(whiteBoardSelector.getConnectCornerLineWidth()));
        binding.tvSelectorCornerWidthValue.setText(String.valueOf(whiteBoardSelector.getCornerWidth()));

        // 触控点样式
        WhiteBoardTouchStyle touchStyle = mController.getTouchStyle();
        binding.tvTouchColorValue.setText(String.format(Locale.ROOT, FORMAT_STRING, touchStyle.getColor()));
        binding.tvTouchSizeValue.setText(touchStyle.getSize().toString());

        // 是否可撤销
        binding.tvIsCanUndoValue.setText(String.valueOf(mController.isCanUndo()));

        // 是否可恢复
        binding.tvIsCanRedoValue.setText(String.valueOf(mController.isCanRedo()));
        binding.tvLimitPageValue.setText(String.valueOf(mController.getLimitPage()));
        binding.tvCurrentBoardValue.setText(String.valueOf(mController.getCurrentBoard()));
        binding.tvCurrentPageValue.setText(String.valueOf(mController.getCurrentPage()));
        binding.tvPageCountsValue.setText(String.valueOf(mController.getPageCounts()));

        Point canvasPos = mController.getCanvasPosition();
        binding.tvCanvasPositionValue.setText(String.format(Locale.ROOT, "(%d,%d)", canvasPos.x, canvasPos.y));
        binding.tvCanvasScaleValue.setText(String.valueOf(mController.getCanvasScale()));

        // Canvas未锁定时，才支持缩放
        boolean isCanvasLock = mController.isCanvasLock();
        binding.tvIsCanvasLockValue.setText(String.valueOf(isCanvasLock));
        binding.canvasScaleDec.setEnabled(!isCanvasLock);
        binding.canvasScaleInc.setEnabled(!isCanvasLock);

        binding.tvSdkVersionValue.setText(WhiteboardServiceController.getSdkVersion());
        binding.tvPlatformVersionValue.setText(mController.getPlatformVersion());

        String recognitionLang = (recognitionLangList != null && !recognitionLangList.isEmpty())
            ? String.join(",", recognitionLangList) : "";
        binding.tvRecognitionLangValue.setText(recognitionLang);
    }

    private void updatePen() {
        // 画笔样式
        WhiteBoardPen pen = mController.getPen();
        int color = pen.getColor();
        int resId = R.drawable.selector_toolbar_pen_white;
        for (int index = 0; index < PICKER_COLORS.length; index++) {
            if (PICKER_COLORS[index] == color) {
                resId = PICKER_COLORS_DRAWABLE[index];
                break;
            }
        }

        binding.ivPenColorValue.setImageResource(resId);
        binding.ivPenColorValue.setSelected(true);

        binding.tvPenWidthValue.setText(String.valueOf(pen.getWidth()));
        binding.tvPenTypeValue.setText(pen.getType().name());
    }

    private void updateCanvasPosition(Point point) {
        if (point == null) {
            return;
        }
        if (mController != null) {
            mController.setCanvasPosition(point);
        }
        if (binding != null) {
            Point canvasPos = mController.getCanvasPosition();
            binding.tvCanvasPositionValue.setText(String.format(Locale.ROOT, "(%d,%d)", canvasPos.x, canvasPos.y));
        }
    }

    @NonNull
    @Override
    protected View onCreateContentView(@NonNull Context context) {
        binding = PopWindowMoreBinding.inflate(((Activity) context).getLayoutInflater());
        return binding.getRoot();
    }

    @Override
    protected String getTag() {
        return TAG;
    }
}
